﻿using System;
using System.Collections.Generic;
using System.Text;
using VMExplorer.MemoryObjects;
using VMExplorer.Win32;

namespace VMExplorer
{
  class RegionInfo
  {
    public static RegionInfo Empty = new RegionInfo ();

    #region Private fields

    private Native.MEMORY_BASIC_INFORMATION _mbi;
    private RegionUsage _usage;

    #endregion
    #region Public properties

    public virtual MemoryAddress Start { get { return new MemoryAddress (_mbi.BaseAddress); } }
    public virtual UInt32 Size { get { return _mbi.RegionSize; } }
    public virtual MemoryAddress Base { get { return new MemoryAddress (_mbi.AllocationBase); } }
    public virtual Native.PAGE_TYPE Type { get { return _mbi.Type; } }
    public virtual Native.MEMORY_PROTECTION Protect { get { return _mbi.Protect; } }
    public virtual Native.PAGE_STATE State { get { return _mbi.State; } }

    public virtual RegionUsage Usage 
		{ 
			get 
			{
				return Related.Count>0 ? Related[0].Type : _usage;
			} 
		}

    public virtual string Description
    {
      get
      {
				string sName = string.Empty;

				foreach (IMemoryObject mo in Related)
				{
					if (sName != string.Empty)
					{
						if (mo.Name != string.Empty)
						{
							sName += " / " + mo.Name;
						}
					}
					else
					{
						sName = mo.Name;
					}
				}

        return sName;
      }
    }

    public List<IMemoryObject> Related { get; private set; }

    #endregion
    #region Construction

    public RegionInfo (Native.MEMORY_BASIC_INFORMATION mbi)
    {
      Related = new List<IMemoryObject> ();
      _mbi = mbi;
      _usage = RegionUsage.Free;
      if (mbi.State != Native.PAGE_STATE.MEM_FREE) _usage = RegionUsage.VirtualAllocated;
    }

    private RegionInfo ()
    {
      Related = new List<IMemoryObject> ();
      _mbi.BaseAddress = MemoryAddress.Invalid;
      _mbi.RegionSize = 0;
      _mbi.AllocationBase = MemoryAddress.Invalid;
      _mbi.Type = 0;
      _mbi.Protect = 0;
      _mbi.State = 0;
      _usage = RegionUsage.Undefined;
    }

    #endregion
    #region Helpers

    public bool Contains (MemoryAddress ma)
    {
      return Start <= ma && ma < Start + Size;
    }

    #endregion
    #region Object overrides

    public override string ToString ()
    {
      return string.Format ("[{0}] {1}-{2}", Base, Start, Start + Size);
    }

    #endregion
  }
}
